#ifndef RECVER_H
#define RECVER_H

#include "utils.h"
#include <netinet/in.h>

class Recver{
public:
	static const int BUFFER_SIZE = 1024;
	static const int MAX_EVENT_NUMBER = 256;
	static const int DOUBLE_SIZE = sizeof(double);

	//单例模式
	static Recver* getRecver() {
		static Recver recver;
		return &recver;
	}

	~Recver() {}

	void init(const Config& conf) {
		port = conf.port;
		tList.window = conf.window;
		interval = conf.interval;

		//初始化管道，内核事件表，设置信号处理函数
		epollfd = epoll_create(5);
		assert(epollfd != -1);

		int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sig_pipe);
		assert(ret != -1);

		setnonblocking(sig_pipe[1]);
		addfd(epollfd, sig_pipe[0]);

		addsig(SIGALRM, sig_handler);
		addsig(SIGINT, sig_handler);
	}

	void run() {
		listenfd = socket(PF_INET, SOCK_STREAM, 0);
    	assert(listenfd >= 0);

		struct sockaddr_in address;
		bzero(&address, sizeof(address));
		address.sin_family = AF_INET;
		address.sin_addr.s_addr = htonl(INADDR_ANY);
		address.sin_port = htons(port);

		int ret = 0;
		ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
		assert(ret != -1);

		ret = listen(listenfd, 5);
		assert(ret != -1);

		addfd(epollfd, listenfd);

		printf(
			"aMin\taMax\taAvg\taSdv\taMid\t"
			"bMin\tbMax\tbAvg\tbSdv\tbMid\t"
			"abMin\tabMax\tabAvg\tabSdv\tabMid\t"
			"abCov\tabCor\tltSize\n"
		);

		bool run_tag = true;  //是否继续运行
		alarm(interval);
		while (run_tag) {
			int number = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
			
			//SIGINT和SIGALRM信号都会中断epoll_wait调用并设置errno为EINTR
			if (number < 0 && errno != EINTR) {
				printf("Recver.run: epoll_wait error.\n");
				break;
			}

			for (int i = 0; i < number; ++i) {
				int sockfd = events[i].data.fd;

				if (sockfd == listenfd && events[i].events & EPOLLIN) {  //处理新连接
					struct sockaddr_in sender_addr;
					socklen_t sender_addr_len = sizeof(sender_addr);
					int connfd = accept(listenfd, (struct sockaddr*)&sender_addr, 
						&sender_addr_len);
					if (connfd < 0) {
						printf("Recver.run: accept new link error.\n");
						continue;
					}
					addfd(epollfd, connfd);
				} else if (sockfd == sig_pipe[0]) {  //处理信号
					int bytes = recv(sockfd, sigBuffer, sizeof(sigBuffer), 0);
					if (bytes <= 0) {
						printf("Recver.run: recv sig_pipe error.\n");
						continue;
					}
					for (int i = 0; i < bytes; ++i) {
						if (sigBuffer[i] == SIGINT) {
							run_tag = false;
						} else if (sigBuffer[i] == SIGALRM) {
							time_t cur = time(NULL);
							tList.ticker(cur);
							tList.calPrint();
							alarm(interval);
						} else {
							continue;
						}
					}
				} else {  //处理dataSender发送来的数据
					if (events[i].events & EPOLLRDHUP) {
						removefd(epollfd, sockfd);
						continue;
					}
					int counts = recv(sockfd, dataBuffer, BUFFER_SIZE * DOUBLE_SIZE, 0);
					if (counts < 0) {
						printf("Recver.run: recv senderData error.\n");
						continue;
					} else if (counts == 0) {
						removefd(epollfd, sockfd);
						continue;
					}
					time_t cur = time(NULL);
					counts /= DOUBLE_SIZE;
					for (int i = 0; i < counts; i += 2) {
						tList.addNode(timerNode(cur, dataBuffer[i], 
							dataBuffer[i+1], dataBuffer[i] * dataBuffer[i+1]));
					}
				}
			}
		}
		close(listenfd);
		close(epollfd);
		close(sig_pipe[0]);
		close(sig_pipe[1]);
	}

private:
	Recver() {}

private:
	int port;
	time_t interval;

	//内核事件表
	int epollfd;
	//监听描述符
	int listenfd;
	//时间升序链表
	timerList tList;
	//接收数据的缓冲区
	double dataBuffer[BUFFER_SIZE];
	//接收信号的缓冲区
	char sigBuffer[BUFFER_SIZE];
	//epoll就绪事件列表
	epoll_event events[MAX_EVENT_NUMBER];
};

#endif